package com.example.automatic.okhttp;

import android.view.WindowManager;

import com.blankj.utilcode.util.StringUtils;
import com.example.automatic.utils.LogUtils;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

public class WebSocketManager {

    private static WebSocketManager mWebSocketManager = null;

    private final static int MAX_NUM = 10;       // 最大重连数
    private final static int MILLIS = 5000;     // 重连间隔时间，毫秒
    private int connectCount = 0;               //连接次数

    private WebSocket mWebSocket;

    private OnWebSocketListener mOnWebSocketListener;

    private boolean isConnect = false;

    public static WebSocketManager getInstance() {
        if (mWebSocketManager == null) synchronized (WindowManager.class) {
            if (mWebSocketManager == null) {
                mWebSocketManager = new WebSocketManager();
            }
        }
        return mWebSocketManager;
    }

    public void setOnWebSocketListener(OnWebSocketListener mOnWebSocketListener) {
        this.mOnWebSocketListener = mOnWebSocketListener;
    }

    /**
     * 是否连接
     */
    public boolean isConnect() {
        return mWebSocket != null && isConnect;
    }

    /**
     * 连接
     */
    public void connect() {
        if (isConnect()) {
            LogUtils.e("WebSocket已经连接！");
        } else {
            OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
                    .writeTimeout(60, TimeUnit.SECONDS)
                    .readTimeout(60, TimeUnit.SECONDS)
                    .connectTimeout(60, TimeUnit.SECONDS)
                    .build();
            Request mRequest = new Request.Builder().url("ws://echo.websocket.org").build();
            mOkHttpClient.newWebSocket(mRequest, createListener());
        }
    }

    /**
     * 重连
     */
    public void reconnect() {
        if (connectCount <= MAX_NUM) {
            try {
                Thread.sleep(MILLIS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            connect();
            connectCount++;
        } else {
            LogUtils.e("重连超过" + MAX_NUM + "次,请检查地址或网络");
        }
    }

    /**
     * 发送消息
     *
     * @param text 字符串
     * @return boolean
     */
    public boolean sendMessage(String text) {
        if (!isConnect())
            return false;
        return mWebSocket.send(text);
    }

    /**
     * 发送消息
     *
     * @param byteString 字符集
     * @return boolean
     */
    public boolean sendMessage(ByteString byteString) {
        if (!isConnect())
            return false;
        return mWebSocket.send(byteString);
    }

    /**
     * 关闭连接
     */
    public void close() {
        if (isConnect()) {
            mWebSocket.cancel();
            mWebSocket.close(1001, "客户端主动关闭连接");
        }
    }

    private WebSocketListener createListener() {
        return new WebSocketListener() {
            @Override
            public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) {
                super.onClosed(webSocket, code, reason);
                mWebSocket = null;
                isConnect = false;
                if (mOnWebSocketListener != null) {
                    mOnWebSocketListener.onClose();
                }
            }

            @Override
            public void onClosing(@NotNull WebSocket webSocket, int code, @NotNull String reason) {
                super.onClosing(webSocket, code, reason);
                mWebSocket = null;
                isConnect = false;
                if (mOnWebSocketListener != null) {
                    mOnWebSocketListener.onClose();
                }
            }

            @Override
            public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) {
                super.onFailure(webSocket, t, response);
                isConnect = false;
                if (mOnWebSocketListener != null) {
                    mOnWebSocketListener.onConnectFailed();
                }
                if (!StringUtils.isEmpty(t.getMessage()) && !t.getMessage().equals("Socket closed")) {
                    reconnect();
                }
            }

            @Override
            public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {
                super.onMessage(webSocket, text);
                if (mOnWebSocketListener != null) {
                    mOnWebSocketListener.onMessage(text);
                }
            }

            @Override
            public void onMessage(@NotNull WebSocket webSocket, @NotNull ByteString bytes) {
                super.onMessage(webSocket, bytes);
                if (mOnWebSocketListener != null) {
                    mOnWebSocketListener.onMessage(bytes.base64());
                }
            }

            @Override
            public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) {
                super.onOpen(webSocket, response);
                mWebSocket = webSocket;
                if (!(isConnect = response.code() == 101)) {
                    reconnect();
                } else {
                    if (mOnWebSocketListener != null) {
                        mOnWebSocketListener.onConnectSuccess();
                    }
                }
            }
        };
    }

}
